package com.zf.thread_pool.thread_first;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 自定义线程工厂
 */
public class CustomThreadFactory implements ThreadFactory {
    public static Logger log = LoggerFactory.getLogger(CustomThreadFactory.class);

    /**
     * 线程组
     */
    private final ThreadGroup group;

    /**
     * 记录当前线程工厂实例对象 创建了多少个线程
     */
    private final AtomicInteger threadNumber = new AtomicInteger(0);

    /**
     * 线程名前缀
     */
    private final String namePrefix;

    /**
     * @param threadPoolName 线程池的名字
     */
    public CustomThreadFactory(String threadPoolName) {
        // 初始化线程工厂对象的一些配置
        SecurityManager s = System.getSecurityManager();
        // 线程组
        group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        // 线程名的前缀
        namePrefix = threadPoolName + "#thread-";
    }

    /**
     * 创建线程对象
     */
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, namePrefix + threadNumber.incrementAndGet(), 0);
        // 当JVM进程中的所有 "非daemon（后台）线程" 都结束了，只剩 daemon 线程时，JVM进程会退出，所有的daemon线程直接被杀死。
        // 设置为线程池中创建的线程为 非 daemon 线程（后台线程）
        t.setDaemon(false);
        // 设置默认的优先级
        t.setPriority(Thread.NORM_PRIORITY);

        // 设置线程中运行的代码出现异常时的处理逻辑
        // 线程的创建和销毁比较消耗资源，定义异常处理，可以在线程中的代码发生异常时，进行处理，防止线程被销毁
        t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                // 获取异常栈的前5个信息，不足5个的取全部信息
                StackTraceElement[] stackTrace = e.getStackTrace();
                String errorMessage = Arrays.asList(stackTrace).subList(0, Math.min(stackTrace.length, 5))
                        .stream().map(StackTraceElement::toString).collect(Collectors.joining("\n"));
                errorMessage = e.toString() + "\n" + errorMessage;

                // 打印异常信息
                log.error("异常信息：{}", errorMessage);
            }
        });

        return t;
    }
}
    